[JavaScript]Ajvでschema検証テストをする際の注意点

[JavaScript]Ajvでschema検証テストをする際の注意点

PostmanでAjvライブラリを使用してschemaを検証するテストを書いたときにはまったことをまとめます。
Clock Icon2024.09.05

SBJソリューション部のserinaです。

PostmanでAjvライブラリを使用してschemaを検証するテストを書いたのですが、意外とスムーズに行かなかったので注意点、というか、はまった内容をまとめます。

やりたかったこと

OpenAPI仕様に書かれているschemaをそのまま貼り付けて、schema検証テストに使用したかったです。

はまったところ

type: integer の際にnullが許容されずエラーになる

format: "int64" を書くとエラーになります。
Ajvはデフォルトではこのformatを認識してくれないようです。

解決方法

ajvのaddFormatを使用して設定します。

https://ajv.js.org/guide/formats.html#user-defined-formats

const Ajv = require('ajv');
ajv.addFormat('int64', true);

addFormatにvalidateを記載できるのですがバグなのか機能していないため、ひとまずこれでエラー回避するようにしています。
もっと良い書き方があれば教えてほしいです。

Ajvで "nullable": true が認識されない

schemaに "nullable": true と記載しているのに、このようなエラーが出てnullが許容されなかったです。

Validation errors: data.XXXX should be integer

解決方法

newするときにnullを許容する設定を行います。

const Ajv = require('ajv');
const ajv = new Ajv({nullable: true});

$refとallOfを取り除いたschemaが必要

ymlファイルで作成していたため、jsonファイルに変換して貼り付ける必要がありました。
しかし、$refやallOfを使用していたためそのままではテストがうまくいかず、純粋なschemaに変換する必要がありました。

解決方法

以下、2つのjsライブラリを使用して変換後のファイルを生成し、そのファイルのschemaを使用することにしました。

また、今回は詳しく書きませんが、このファイルをdockerで定期的に実行することで常に最新のjsonファイルが作成されるようにもしました。

jsファイル
main.js
const SwaggerParser = require('@apidevtools/swagger-parser');
const mergeAllOf = require('json-schema-merge-allof');
const fs = require('fs');

/**
 * $refを取り除き、allOfを展開してファイル出力
 * @param {*} inputFilePath 
 * @param {*} outputFilePath 
 */
async function processOpenAPISchema(inputFilePath, outputFilePath) {
  try {
    // $refをなくす
    const api = await SwaggerParser.dereference(inputFilePath);

    // allOfを展開し、順序を保ったスキーマを作成する
    function processSchema(schema) {
      if (schema && typeof schema === 'object') {
        if (schema.allOf) {
          schema = mergeAllOf(schema, { resolvers: {} });
        }
        for (const key in schema) {
          schema[key] = processSchema(schema[key]);
        }
        if (schema.type === 'object') {
          return {
            type: schema.type,
            properties: schema.properties,
            required: schema.required,
          };
        }
      }
      return schema;
    }

    // $refをなくしたOpenAPIからallOfもなくす
    const processedApi = processSchema(api);

    // 結果をファイルに書き出す
    fs.writeFileSync(outputFilePath, JSON.stringify(processedApi, null, 2));
    console.log('Processed OpenAPI schema written to', outputFilePath);
  } catch (err) {
    console.error('Error processing OpenAPI schema:', err);
  }
}

processOpenAPISchema('index.yml', 'openapi-without-allOf-and-ref.json');
実行方法
node main.js

最後に

ジェネレータ生成のライブラリはいくつかあったので、json schemaを生成するライブラリに辿り着くのに結構時間をかけてしまいました。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.